package services

import (
	"demo/enmu"
	"demo/models"
	"demo/pkg/database"
	"demo/pkg/notice"
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"gonum.org/v1/gonum/floats"
	"gonum.org/v1/gonum/stat"
)

//生成用电分析报告，并提供用电建议和节能建议
func ElectricityUsageReport(c *gin.Context) {
	user := getUserInfo(c)
	resp := models.GetDefaultResp()
	report, err := electricityUsageReport(user.Id)
	if err != nil {
		resp.Code, resp.Msg = enmu.BAD_REGIRSTER_INFO_CODE, enmu.BAD_REGIRSTER_INFO_MSG
		c.JSON(http.StatusBadRequest, resp)
		return
	}

	// 发送电费使用报告
	err = sendElectricityUsageReport(c, report)
	if err != nil {
		resp.Code, resp.Msg = enmu.BAD_REGIRSTER_INFO_CODE, err.Error()
		c.JSON(http.StatusInternalServerError, resp)
		return
	}

	resp.Data = report
	c.JSON(http.StatusOK, resp)
}

//生成电费使用报告数据
func electricityUsageReport(userId int) (*models.ElectricityUsageStats, error) {
	bills, err := database.GetElectricityBillsByUserId(userId)
	if err != nil {
		logrus.Error("failed to query electricity bills: ", err)
		return nil, err
	}

	if len(bills) == 0 {
		return nil, errors.New("no bills found for the user")
	}

	var usage []float64
	var amounts []float64
	for _, bill := range bills {
		usage = append(usage, float64(bill.ElectricityUsage))
		amounts = append(amounts, float64(bill.Amount))
	}

	// 计算统计数据
	meanUsage := stat.Mean(usage, nil)
	meanAmount := stat.Mean(amounts, nil)
	stdUsage := stat.StdDev(usage, nil)
	stdAmount := stat.StdDev(amounts, nil)
	totalUsage := floats.Sum(usage)
	totalAmount := floats.Sum(amounts)

	// 格式化为两位小数
	formattedMeanUsage, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", meanUsage), 64)
	formattedMeanAmount, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", meanAmount), 64)
	formattedStdUsage, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", stdUsage), 64)
	formattedStdAmount, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", stdAmount), 64)
	formattedTotalUsage, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", totalUsage), 64)
	formattedTotalAmount, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", totalAmount), 64)

	// 创建结构体实例
	report := &models.ElectricityUsageStats{
		MeanUsage:   formattedMeanUsage,
		MeanAmount:  formattedMeanAmount,
		StdUsage:    formattedStdUsage,
		StdAmount:   formattedStdAmount,
		TotalUsage:  formattedTotalUsage,
		TotalAmount: formattedTotalAmount,
	}


	// 提供建议
	var suggestions string

	if stdUsage < 200 {
		suggestions = "您的用电量较低，继续保持节约使用电能的好习惯，可以考虑进一步优化家庭电器的能效。"
	} else if stdUsage >= 200 && stdUsage < 400 {
		suggestions = "您的用电量处于正常范围，建议使用节能灯具来替换传统照明设备，定期清洁空调滤网以保持其高效运行，并合理使用家电，如避免同时使用多个高耗能家电。"
	} else if stdUsage >= 400 && stdUsage < 600 {
		suggestions = "您的用电量较高，请优化空调使用，设置合适的温度并使用定时开关机功能，考虑购买能耗标识为高效的家电，如能效等级高的冰箱、洗衣机等，并关注电器休眠状态，及时关闭待机电器，如电视、电脑等。"
	}else if stdUsage >= 600 {
		suggestions = "您的用电量非常高，请考虑采取更多的节能措施，如利用电力公司的分时电价优惠，高峰时段避免使用高耗能设备，加强能效改造，定期检查家电以确保最佳工作状态。"
	}
	
	report.Suggestions = suggestions
	
	return report, nil
}

//发送电费使用报告给用户
func sendElectricityUsageReport(c *gin.Context, report *models.ElectricityUsageStats) error {
	user := getUserInfo(c)
	if user == nil {
		logrus.Errorln("获取用户信息失败")
		return errors.New("获取用户信息失败")
	}

	// 准备邮件标题和内容
	title := "【原始人电力公司】电费使用报告"
	content := fmt.Sprintf(
		"尊敬的用户%s，\n\n"+
			"感谢您使用原始人电力公司的服务。以下是您的电费使用报告详情：\n\n"+
			"用户ID: %d\n"+
			"总用电量: %.2f kWh\n"+
			"总金额: %.2f 元\n"+
			"平均用电量: %.2f kWh\n"+
			"平均金额: %.2f 元\n"+
			"用电量标准差: %.2f\n"+
			"金额标准差: %.2f\n\n"+
			"建议：%s\n\n"+
			"请及时缴纳您的电费。如有任何疑问，请联系原始人电力公司客服。\n\n"+
			"谢谢！\n原始人电力公司",
		user.Name,
		user.Id,
		report.TotalUsage,
		report.TotalAmount,
		report.MeanUsage,
		report.MeanAmount,
		report.StdUsage,
		report.StdAmount,
		report.Suggestions,
	)

	noticeMsg := &models.NoticeMsg{
		Title:    title,
		Content:  content,
		UserNums: []string{user.Email},
		Type:     "email", 
	}

	err := notice.SendNoticeToUser(noticeMsg)
	if err != nil {
		logrus.Error("发送电费使用报告失败: ", err)
		return errors.New("发送报告失败")
	}
	//插入usage_report表中的结构体
	usage_report:=models.UsageReports{
		UserId: user.Id,
		ReportDate: 	time.Now(),
		Report: 		content,

	}
	err=database.InsertOneUsageReport(&usage_report)
	if err!=nil{
		return err
	}
	return nil
}

//统计用户每个月的用电量，并返回一个 map，月份作为键，用电量作为值
func MonthlyElectricityUsage(c *gin.Context) {
	user := getUserInfo(c)
	resp := models.GetDefaultResp()

	// 获取用户的电费账单数据
	bills, err := database.GetElectricityBillsByUserId(user.Id)
	if err != nil {
		logrus.Error("failed to fetch electricity bills:", err)
		resp.Code, resp.Msg = enmu.BAD_REGIRSTER_INFO_CODE, enmu.BAD_REGIRSTER_INFO_MSG
		c.JSON(http.StatusBadRequest, resp)
		return
	}

	// 创建一个 map 用于统计每个月的用电量
	monthlyElectricity := make(map[string]float32)

	// 遍历账单，按月统计用电量
	for _, bill := range bills {
		month := bill.BillDate.Format("2006-01")
		monthlyElectricity[month] += bill.ElectricityUsage
	}

	// 确保所有月份都在结果中，没有的月份设置用电量为0
	addMissingMonths(monthlyElectricity)

	resp.Data = monthlyElectricity
	c.JSON(http.StatusOK, resp)
}

// addMissingMonths 确保每个月份都在 map 中，没有的月份用电量设置为0
func addMissingMonths(monthlyElectricity map[string]float32) {
	// 需要检查的月份范围
	startMonth := time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)
	endMonth := time.Date(2024, time.December, 1, 0, 0, 0, 0, time.UTC)

	// 创建一个 map 用于存储需要添加的月份
	missingMonths := make(map[string]float32)

	// 遍历从 startMonth 到 endMonth 的每个月份
	for date := startMonth; !date.After(endMonth); date = date.AddDate(0, 1, 0) {
		monthKey := date.Format("2006-01")
		if _, ok := monthlyElectricity[monthKey]; !ok {
			missingMonths[monthKey] = 0.0
		}
	}

	// 将缺失的月份添加到 monthlyElectricity 中，用电量设置为0
	for month, value := range missingMonths {
		monthlyElectricity[month] = value
	}
}